import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Base64;
import java.util.zip.Inflater;

/**
 * 使用Frida捕获的密钥解密data
 * 
 * 用法：
 * 1. 运行Frida脚本捕获AES密钥
 * 2. 从输出中复制密钥的hex值
 * 3. java TestWithCapturedKey <key_hex> <data_base64> <tn_base64>
 */
public class TestWithCapturedKey {
    
    public static void main(String[] args) {
        if (args.length < 3) {
            System.out.println("用法: java TestWithCapturedKey <key_hex> <data_base64> <tn_base64>");
            System.out.println();
            System.out.println("示例:");
            System.out.println("  java TestWithCapturedKey d18b48...db597 wHBy2LDI... 6rOG");
            System.out.println();
            System.out.println("步骤:");
            System.out.println("  1. 使用Frida运行 hook_complete_flow.js");
            System.out.println("  2. 从输出中找到 'AES密钥' 的hex值");
            System.out.println("  3. 运行此程序验证解密");
            return;
        }
        
        String keyHex = args[0];
        String dataBase64 = args[1];
        String tnBase64 = args[2];
        
        System.out.println("================================================================================");
        System.out.println("使用捕获的密钥解密data");
        System.out.println("================================================================================\n");
        
        try {
            // 解析密钥
            byte[] aesKey = hexToBytes(keyHex);
            System.out.println("✓ AES密钥: " + keyHex);
            System.out.println("  长度: " + aesKey.length + " 字节");
            
            if (aesKey.length != 32) {
                System.err.println("\n✗ 错误: 密钥长度必须是32字节（64个hex字符）");
                System.err.println("  当前长度: " + aesKey.length + " 字节");
                return;
            }
            
            // 解码data
            byte[] dataEncrypted = Base64.getDecoder().decode(dataBase64);
            System.out.println("\n✓ data密文: " + dataEncrypted.length + " 字节");
            
            // 提取IV（前16字节）
            byte[] iv = Arrays.copyOfRange(dataEncrypted, 0, 16);
            byte[] ciphertext = Arrays.copyOfRange(dataEncrypted, 16, dataEncrypted.length);
            
            System.out.println("  IV: " + bytesToHex(iv));
            System.out.println("  密文: " + ciphertext.length + " 字节");
            
            // AES解密
            System.out.println("\n" + "-".repeat(80));
            System.out.println("AES解密");
            System.out.println("-".repeat(80));
            
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
            IvParameterSpec ivSpec = new IvParameterSpec(iv);
            cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
            
            byte[] decrypted = cipher.doFinal(ciphertext);
            System.out.println("✓ AES解密成功！");
            System.out.println("  解密后长度: " + decrypted.length + " 字节");
            
            // 解压缩
            System.out.println("\n" + "-".repeat(80));
            System.out.println("zlib解压缩");
            System.out.println("-".repeat(80));
            
            Inflater inflater = new Inflater(true);  // nowrap=true (wbits=-15)
            inflater.setInput(decrypted);
            
            byte[] decompressed = new byte[65536];  // 64KB buffer
            int decompressedLen = inflater.inflate(decompressed);
            inflater.end();
            
            byte[] result = Arrays.copyOf(decompressed, decompressedLen);
            
            System.out.println("✓ zlib解压缩成功！");
            System.out.println("  解压后长度: " + result.length + " 字节");
            
            // 转换为字符串
            String json = new String(result, StandardCharsets.UTF_8);
            
            System.out.println("\n" + "=".repeat(80));
            System.out.println("✓✓✓ 成功解密data明文！✓✓✓");
            System.out.println("=".repeat(80));
            System.out.println();
            System.out.println(json);
            System.out.println();
            
            // 尝试解密tn
            System.out.println("=".repeat(80));
            System.out.println("尝试解密tn");
            System.out.println("=".repeat(80));
            
            byte[] tnEncrypted = Base64.getDecoder().decode(tnBase64);
            System.out.println("✓ tn密文: " + tnEncrypted.length + " 字节");
            
            if (tnEncrypted.length >= 16) {
                byte[] tnIv = Arrays.copyOfRange(tnEncrypted, 0, 16);
                byte[] tnCiphertext = Arrays.copyOfRange(tnEncrypted, 16, tnEncrypted.length);
                
                System.out.println("  IV: " + bytesToHex(tnIv));
                System.out.println("  密文: " + tnCiphertext.length + " 字节");
                
                cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(tnIv));
                byte[] tnDecrypted = cipher.doFinal(tnCiphertext);
                
                System.out.println("\n✓ tn解密成功！");
                String tnJson = new String(tnDecrypted, StandardCharsets.UTF_8);
                System.out.println(tnJson);
            }
            
            System.out.println("\n" + "=".repeat(80));
            System.out.println("总结");
            System.out.println("=".repeat(80));
            System.out.println("✓ 使用Frida捕获的密钥成功解密了data和tn");
            System.out.println("✓ 证明：AES密钥 = ep加密前的原始值");
            System.out.println("✓ 下一步：提取RSA私钥或继续使用Hook获取密钥");
            
        } catch (Exception e) {
            System.err.println("\n✗ 错误: " + e.getMessage());
            e.printStackTrace();
            
            System.err.println("\n可能的原因:");
            System.err.println("  1. 密钥不正确（确认是32字节的hex）");
            System.err.println("  2. data或tn的Base64格式错误");
            System.err.println("  3. 密钥和数据不匹配（来自不同的调用）");
        }
    }
    
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
    
    private static byte[] hexToBytes(String hex) {
        // 移除所有空格和换行
        hex = hex.replaceAll("\\s+", "");
        
        int len = hex.length();
        if (len % 2 != 0) {
            throw new IllegalArgumentException("Hex字符串长度必须是偶数，当前: " + len);
        }
        
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i+1), 16));
        }
        return data;
    }
}



